module timer(
	input		CLK_I,
	input		RST_I,
	input		CYC_I,
	input		STB_I,
        input		 WE_I,
	output		ACK_O,
	input	[2:2]	ADR_I,
	input	[31:0]	DAT_I,
	input	[3:0]	SEL_I,
	output	[31:0]	DAT_O,
	output		o_irq
);

// offset 0-1
reg	en;
// offset 1-2
reg	irq;
// offset 4-8
reg	[31:0]	reload;

reg	[31:0]	counter;

wire	write_en  = (CYC_I & STB_I & WE_I) & ADR_I == 1'b0 & SEL_I[0];
wire	write_irq = (CYC_I & STB_I & WE_I) & ADR_I == 1'b0 & SEL_I[1];

// 若向en写入1则为reload，否则为counter-1
wire	[31:0]	counter_nxt = (write_en & DAT_I[0]) | counter == 32'b0 ? reload : counter-32'b1;

always @(posedge CLK_I) begin
  counter <= RST_I ? 32'b0 : counter_nxt;
  if (RST_I) begin
    en <= 1'b0;
    irq <= 1'b0;
    reload <= 32'b0;
  end else begin
    irq <= write_irq ? DAT_I[8] : irq | (en & counter == 32'b0);
    if (CYC_I & STB_I & WE_I) begin
      if (ADR_I[2]) begin
        if (SEL_I[0]) reload[ 7: 0] <= DAT_I[ 7: 0];
        if (SEL_I[1]) reload[15: 8] <= DAT_I[15: 8];
        if (SEL_I[2]) reload[23:16] <= DAT_I[23:16];
        if (SEL_I[3]) reload[31:24] <= DAT_I[31:24];
      end else begin
        if (SEL_I[0]) en <= DAT_I[0];
      end
    end
  end
end

wb_ack u_wb_ack(
	.CLK_I(CLK_I),
	.RST_I(RST_I),
	.CYC_I(CYC_I),
	.STB_I(STB_I),
	.ACK_O(ACK_O)
);

assign	DAT_O = ADR_I[2] ? reload : {16'b0, 7'b0, irq, 7'b0, en};
assign	o_irq = irq;

endmodule
